import {SelfEventListener} from "@/api/common.ts";
import {dayjs} from "element-plus";

export class Common {

    /**
     * 清除所有定时器 循环器和监听
     * @param list 事件
     */
    static clearAllEventListener(list: SelfEventListener) {
        let {time, interval, listener} = list

        for (let i = 0; i < time.length; i++) {
            clearTimeout(time[i])
        }
        for (let i = 0; i < interval.length; i++) {
            clearInterval(interval[i])
        }
        for (let i = 0; i < listener.length; i++) {
            listener[i].userCapture.removeEventListener(listener[i].event, listener[i].func)
        }
    }

    /**
     * 如果是16进制则返回rgb不是则直接返回
     * @param color
     */
    static checkColorFormat(color): any {
        // 判断是否为16进制颜色代码
        const isHex = /^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/.test(color);
        // 判断是否为RGB颜色值
        const isRgb = /^rgb\((\d{1,3}),(\d{1,3}),(\d{1,3})\)$/.test(color);

        if (isHex) {
            // 将16进制颜色代码转换为RGB颜色值
            const hex = color.slice(1); // 去掉#号
            const r = parseInt(hex.slice(0, 2), 16); // 提取红色分量
            const g = parseInt(hex.slice(2, 4), 16); // 提取绿色分量
            const b = parseInt(hex.slice(4, 6), 16); // 提取蓝色分量
            return `rgb(${r},${g},${b})`; // 返回RGB颜色值
        } else if (isRgb) {
            return color;
        } else {
            return false; // 如果既不是16进制颜色代码也不是RGB颜色值，则返回false
        }
    }

    /**
     *
     * 判断是否为合法的RGB颜色值
     * @param rgb
     * @return 返回一个{}对象
     */
    static parseRGB(rgb) {
        const regex = /^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/;
        const result = regex.exec(rgb);

        if (result) {
            return {
                r: parseInt(result[1], 10),
                g: parseInt(result[2], 10),
                b: parseInt(result[3], 10)
            };
        } else {
            throw new Error('Invalid RGB color format');
        }
    }

    /**
     * 获取互补色
     * @param rgb
     */
    static getComplementaryColor(rgb: { r: number; b: number; g: number }) {
        return `rgb(${255 - rgb.r},${255 - rgb.g},${255 - rgb.b})`
    }

    /**
     * 判断是否为深色
     */
    static isDark(red: number, green: number, blue: number) {
        let brightness = (red * 299 + green * 587 + blue * 114) / 1000;
        return brightness < 128;
    }

    /**
     * 根据传入的hex或者rgb判断是否为深色
     */
    static isDarkByHexOrRgb(hexOrRgb: string) {
        let format = this.checkColorFormat(hexOrRgb);
        if (!format) return false
        let rgb = this.parseRGB(format);
        return this.isDark(rgb.r, rgb.g, rgb.b);
    }

    /**
     * 检测对象值是否为空
     * @param object
     */
    static checkObjectValueIsNull(object: Object): boolean {
        // 遍历对象
        for (const key in object) {
            // 如果对象值为空或者undefined，则返回false
            if (object[key] == null || object[key] == undefined) {
                return false;
            }
        }
        // 否则返回true
        return true;
    }

    /**
     * 深拷贝
     * @param obj 拷贝对象
     */
    static deepCopy<T>(obj: T): T {
        if (obj === null || typeof obj !== 'object') {
            return obj;
        }
        let copy = obj.constructor();
        for (let attr in obj) {
            if (obj.hasOwnProperty(attr)) {
                copy[attr] = Common.deepCopy(obj[attr]);
            }
        }
        return copy;
    }

    /**
     * 将一个对象转化为另一个对象
     *
     * @param target 目标对象
     * @param source 源对象
     */
    static objectAssign<T, S>(target: T, source: S): T {
        if (source) {
            for (let key in source) {
                if (target.hasOwnProperty(key)) {
                    (target as any)[key] = (source as any)[key];
                }
            }
        }
        return target as T;
    }

    /**
     * 判断对象是否相等
     */
    static deepEqual(obj1: {}, obj2: {}): boolean {
        if (obj1 === obj2) {
            return true;
        }

        if (typeof obj1 !== 'object' || obj1 === null || typeof obj2 !== 'object' || obj2 === null) {
            return false;
        }

        let keys1 = Object.keys(obj1);
        let keys2 = Object.keys(obj2);

        if (keys1.length !== keys2.length) {
            return false;
        }

        for (let key of keys1) {
            if (!keys2.includes(key) || !this.deepEqual(obj1[key], obj2[key])) {
                return false;
            }
        }

        return true;
    }

    /**
     * 计算平均值
     * @param list 数据列表
     * @param props 需要计算的属性名
     */
    static calculateAverage(list, ...props) {
        return props.reduce((result, prop) => {
            let realSize = list.length
            result[prop] = list.map(obj => obj[prop]).reduce((sum, val) => {
                if (isNaN(Number(val))) {
                    realSize--
                    return sum;
                }
                return sum + Number(val);
            }, 0) / realSize;
            return result;
        }, {});
    }

    /**
     * 计算四舍五入
     * @param list 需要计算的数据
     *  @param props 需要计算的属性名
     */
    static calculateRound(list: {}, ...props) {
        return props.reduce((result, prop) => {
            result[prop] = parseFloat(list[prop].toFixed(1))
            return result
        }, {})
    }

    /**
     * 计算四舍五入
     * @param list 需要计算的数据
     *  @param props 需要计算的属性名
     */
    static calRound<T>(list: T, props: {}) {
        let names = Object.getOwnPropertyNames(props);
        return Object.getOwnPropertyNames(list).reduce((result, item) => {
            result[item] = names.includes(item) ? parseFloat(list[item]).toFixed(1) : list[item]
            return result
        }, {})
    }

    static formatTime(date: Date | string, format: string = 'HH:mm:ss') {
        return dayjs(date).format(format)
    }

    static getViewPointSize(viewPoint: number) {
        return window.innerWidth / 100 * viewPoint
    }

    static createUUID() {
        return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
            let r = Math.random() * 16 | 0,
                v = c == 'x' ? r : (r & 0x3 | 0x8);
            return v.toString(16);
        });
    }

    static deepMerge(target, ...sources) {
        if (!sources.length) return target;
        const source = sources.shift();

        if (Common.isObject(target) && Common.isObject(source)) {
            for (const key in source) {
                if (Common.isObject(source[key])) {
                    if (!target[key]) Object.assign(target, {[key]: {}});
                    Common.deepMerge(target[key], source[key]);
                } else {
                    Object.assign(target, {[key]: source[key]});
                }
            }
        }

        return Common.deepMerge(target, ...sources);
    }

    static isObject(item) {
        return (item && typeof item === 'object' && !Array.isArray(item));
    }
}